#include "face.h"
#include "ui_face.h"

face::face(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::face)
{
    ui->setupUi(this);
    // 打开摄像头
     cap.open(0);
     startTimer(100);// 每隔100ms调用一次timerEvent,读取摄像头数据

     //导入 级联分类器文件
    if(!cascade.load("D:\\opencv2\\opencv-4.5.4\\opencv-4.5.4\\build\\install\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml"))
     {
         qDebug()<<"加载错误";
     }


      connect(&mtim,&QTimer::timeout,this,&face::to_connect);//5s 到了就连接服务器
      connect(&msocket,&QTcpSocket::connected,this,&face::to_stop);//已经连接到服务器就不用定时5s去连接服务器了
      connect(&msocket,&QTcpSocket::disconnected,this,&face::to_start);//断开连接就重新计时5s连接服务器


      connect(&msocket,&QTcpSocket::readyRead,this,&face::read_data);//收到信息调用read_data函数
      mtim.start(5000);//5s 调用
      flag=0;//构造函数中对检测人脸的次数赋值
      ui->widget_2->hide();// 认证成功先隐藏先隐藏

}
void face::timerEvent(QTimerEvent *e)
{
     Mat srcimage;
     if(cap.grab())//如果 捕捉到一帧数据
     {
        cap.read(srcimage);//读到该变量中


     }

     //新增
      Mat grayimage;
      cvtColor(srcimage,grayimage,COLOR_BGR2GRAY);//转化为灰度 图像

        if(!grayimage.empty())
        {
          std::vector<Rect> faceRects;// vector来存放 有人脸的矩形坐标数据
          cascade.detectMultiScale(grayimage,faceRects);// 检测如果有人脸，将帧图片放到vector中,
          if(faceRects.size()>0&&flag>=0)// 如果vector中有数据，表示有人脸，添加flag>=0
          {
              Rect rect=faceRects.at(0);//将第一次 捕捉到的人脸数据 放到该矩形变量中
             //rectangle(srcimage,rect,Scalar(255,0,0));
             ui->flag->setGeometry(rect.x,rect.y,rect.width,rect.height);//flag是我们之前设置的标签上面贴着圈，我们设置改标签位置为 人脸矩形位置即可
              /*    2-8    */
            if(flag>2)
            {
           //将视频一帧数据Mat数据转化为QbyteAray --->编码为jpg格式
             std::vector<uchar>buf;// 存放转化后的jpg格式的视频一帧数据
             cv::imencode(".jpg",srcimage,buf);//编码转化----->将srcimage图像编码转化为jpg结构，存放在buf中
             QByteArray byte((const char*)buf.data(),buf.size());//将字符串转化为QByteArray放在Byte中
            //    准备发送
             quint64 backsize=byte.size();//获取编码 后数据的大小
             QByteArray senddata;
             QDataStream stream(&senddata,QIODevice::WriteOnly);//以写 字节流方式打开 senddata
             stream.setVersion(QDataStream::Qt_5_14);//设置版本,不同版本有不同的序列方式
             stream<<backsize<<byte;//构建写入格式相当于sprintf
             msocket.write(senddata);//向服务器发送视频数据

             facemat=srcimage(rect);//   捕捉第一张人脸
             cv::imwrite("./face.jpg",facemat);//保存图片
             flag=-2;//*******************修改为-2*********************//
            }
            flag++;

          }
          if(faceRects.size()==0)//如果是 第二张人脸/没有脸的话就会重新进行上传
          {
              flag=0;

          }


         }

       if(srcimage.data==nullptr)return ; //没读到视频数据
        // 把opencv里面的Mat格式数据（BGR）转化为qt中的Qimage(RGB)
        cvtColor(srcimage,srcimage,COLOR_BGR2RGB);
        QImage image(srcimage.data,srcimage.cols,srcimage.rows,srcimage.step1(),QImage::Format_BGR888);
        QPixmap mp=QPixmap::fromImage(image);//将QImage  转化为 QPixmap用来显示
        ui->vedio->setPixmap(mp);//给标签设置一帧视频数据图片

}

void face::to_connect()
{
   msocket.connectToHost("192.168.0.113",7777);
   qDebug()<<"   正在连接服务器";
}

void face::to_start()
{
      mtim.start(5000);
      qDebug()<<"  已经断开服务器";

}

void face::to_stop()
{
    mtim.stop();
    qDebug()<<"  已经连接到服务器";
}

void face::read_data()
{   //    "{\"employeeID\":\"%1\",\"name\":\"%2\",\"department\":\"%3\",\"time\":\"%4\"}"  // 接收格式
     QByteArray  msg=msocket.readAll();//需要修改为QByteArray接收
     qDebug()<<msg;
     QJsonDocument jsonDoc = QJsonDocument::fromJson(msg);
     QJsonObject obj=jsonDoc.object();
     if(obj.value("employeeID").toString()=="none")//如果人脸不存在的话  每个地方都是none
     {
         QString employeeID=obj.value("employeeID").toString();
         QString name=obj.value("name").toString();
         QString department=obj.value("department").toString();
         QString time=obj.value("time").toString();
         ui->number_1value->setText(employeeID);
         ui->name_value->setText(name);
         ui->department_value->setText(department);
         ui->time_value->setText(time);
         ui->head->setStyleSheet("background-color: rgb(50, 50, 50);border-radius:65px;");//不设置照片
         ui->widget_2->hide();//隐藏 认证成功
 }
     else
     {
                 QString employeeID=obj.value("employeeID").toString();
                 QString name=obj.value("name").toString();
                 QString department=obj.value("department").toString();
                 QString time=obj.value("time").toString();
                 ui->number_1value->setText(employeeID);
                 ui->name_value->setText(name);
                 ui->department_value->setText(department);
                 ui->time_value->setText(time);
                 ui->head->setStyleSheet("background-color: rgb(50, 50, 50);border-radius:65px; border-image: url(./face.jpg);");//设置图片
                  ui->widget_2->show();//显示认证成功

    }

}


face::~face()
{
    delete ui;
}

